iT邦幫忙

2022 iThome 鐵人賽

DAY 3
3
Software Development

30 天與九頭蛇先生做好朋友系列 第 3

OAuth 2.0 授權流程

  • 分享至 

  • xImage
  •  

OAuth 2.0 授權流程裡,關注的重點只有兩個:

  1. 如何取得使用者授權。
  2. 如何向授權伺服器請求 Access Token。

其他細節就不是 OAuth 2.0 授權流程所關注的,如:資源伺服器如何驗證 Access Token,或是授權伺服器如何做身分驗證等。Hydra 的目的也不是在解決這些問題,而是將授權流程與這些細節很好地切分,達到關注點分離的效果,這也是為何第一天提到 Hydra 是一個職責單一的微服務,因為它要處理的領域確實是明確且獨立的。

因為 OAuth 2.0 是一個授權「框架」,裡面定義的都是抽象層次的規範,大致上會分作為兩個類型,一類是角色的定義,另一類是授權類型的定義。

角色定義

OAuth 2.0 協定定義了參與授權流程的四個角色:

角色 說明
Resource Owner 資源擁有者,通常都是指「使用者」。
Resource Server 資源伺服器,用來存放使用者受保護資源的伺服器。
Client 應用程式,泛指對資源擁有者的資源有興趣的服務。
Authorization Server 授權伺服器,專門用來處理授權的伺服器。

概念上來說,應用程式一開始都是無法「直接」地存取資源的,而是要透過授權伺服器來管理其存取行為。而在這流程中,使用者也有可能會需要參與授權流程,因為使用者通常是有權限管理資源的角色。應用程式必須經過使用者「同意」之後,才會發放憑證,應用程式就能透過憑證來存取資源。

一個實務的例子如:鐵人賽編輯器想做一個功能是能夠插入 Google 雲端硬碟上保存的圖片,但鐵人賽編輯器沒有直接存取參賽者 Google 雲端硬碟的權限,但可以透過 OAuth 2.0 流程來請求參賽者同意「鐵人賽編輯器存取參賽者放在 Google 雲端硬碟的檔案」。

在這個例子中角色對應如下:

  1. 資源擁有者:這裡指的是參賽者。
  2. 資源伺服器:Google 雲端硬碟。
  3. 應用程式:鐵人賽編輯器。
  4. 授權伺服器:Google 身分驗證與授權中心,指 accounts.google.com 這個主機。

而從上面的例子來看,授權流程的最終目標會是:應用程式能夠存取資源伺服器的資源。這個概念在 RFC 6749 - 1.2. Protocol Flow 裡有提到,文件有提出類似像下面的循序圖:

Image.jpeg

應用程式首先要發出授權請求給使用者,接著使用者同意授權後,應用程式會收到授權回應,內容有可能是同意授權,也有可能是其他錯誤。如果使用者同意授權的話,接著再拿同意授權的結果,來跟授權伺服器請求 Access Token--用來存取資源的憑證。應用程式取得 Access Token 之後,即可用來向資源伺服器驗證並請求存取資源。

OAuth 2.0 的授權類型

了解角色和授權概念之後,接著要來了解這些角色可以如何互動。OAuth 2.0 提供了四個預定義的授權類型(Grant Type),同時也設計了擴充空間,讓未來在有其他需求的時候,還能夠方便新增流程,如 RFC 7521 - Assertion Framework for OAuth 2.0 Client Authentication and Authorization Grants 是利用 Assertion(如 SAML AssertionJWT)來換取 Access Token 的框架。

Authorization Code

這是常見也相較安全的授權類型,角色互動的時序圖如下:

Image.jpeg

這個流程有兩個關鍵:

  1. 應用程式主要和使用者互動只有第 1 步,有另外兩個步驟是轉導行為,一個是第 2 步轉導去授權伺服器,另一個是第 5 步轉導回應用程式。這裡可以發現,應用程式是無法控制使用者授權行為,只能由使用者主動按「同意授權」,應用程式才能夠得到成功授權的結果。
  2. 使用者無法看到 Access Token 內容,因此攻擊者要偷取可用的 Token 是困難的。一般攻擊者可以透過植木馬或注入惡意程式碼到使用者電腦中,再讓瀏覽器執行程式把資料傳送給攻擊者。但使用者看不到 Access Token,攻擊的困難度就會提高。

因為 Authorization Code 授權流程設計上是完整且安全的,因此是目前 OAuth 2.0 主流的授權類型。

Implicit

正如其名,在授權流程中有部分的流程是被隱含完成的,主要是在取得 Token 的步驟時,省略了驗證應用程式身分的流程。這容易讓 Access Token 有被「非應用程式身分」的攻擊者偷走的風險。現已被 OAuth 2.0 Security BCP 文件 為不應該(SHOULD NOT)使用的流程,目前大多數的情境都有對應的解法,但只剩 SPA(Single-Page Application,協定裡的專有術語是稱為 Browser-Based Application)有可能還需要使用 Implicit 授權模式,其他基本上都應該採用 Authorization Code 授權模式。

Implicit 流程時序圖如下:

Image.jpeg

問題主要在第 5 步:Access Token 放在 URI 的 Fragment 中。

雖然 HTTP 協定有提到請求資源的時候,不應該把 Fragment 包含在請求資源的一部分,但假設瀏覽器或伺服器沒有按照著這個協定實作的話,就有機會被中間人攻擊;另一方面,即便瀏覽器跟伺服器都有照著規範實作,因為 Fragment 依然是網址的一部分,Javascript 還是有辦法解析並取得 Access Token 的,若被 XSS 攻擊,Access Token 就有被偷的風險。

因為存在這些風險,因此 Implicit 被定為「不應該」使用的流程。

Resource Owner Password Credentials

簡稱為 ROPC。這個授權類型與 Authorization Code 和 Implicit 一樣,會經由使用者授權,但不一樣的是:在這個流程裡,使用者不會經過授權伺服器,而是應用程式直接向使用者要求授權伺服器的驗證資訊來完成授權。

時序圖如下:

Image.jpeg

這個做法與最初提到的問題是類似的--應用程式會接收到使用者的帳號密碼,對使用者來說就會多一層風險。但使用帳密的方法是不同的,ROPC 是用帳密來交換 Access Token,後續存取資源就改用 Access Token,因此後續就不需要再儲存帳密,進而避免帳號密碼存明文的風險。

因為使用者的帳號密碼還是會需要經過應用程式,因此協定是建議這個授權類型僅用在應用程式是高度可信賴的時候,比方說應用程式是另一個子公司所開發的。

但是!事實上各種文章或是理論,都在說明 ROPC 授權類型存在非常多問題,包括 Hydra 也是,Hydra 並沒有也不打算實作 ROPC 授權類型,有部分與原生應用程式授權流程有關,這會留到未來的章節再來說明,其餘原因可以參考這篇文章

Client Credentials

應用程式直接跟授權伺服器做驗證,不透過使用者授權。時序圖如下:

Image.jpeg

主要應用在「應用程式本身就是資源擁有者」的情境,因此 Access Token 只能管理應用程式本身能管理的資源。像 GitHub 的 Personal Access Token 就是類似這樣的應用,只是它代表的是帳號的使用者本人,而不是應用程式。

本日小結

今天說明了角色定義與四種基本授權類型的定義,明天接續來說明跟它關係很深的 OpenID Connecrt。


上一篇
OAuth 2.0 協定簡介
下一篇
OpenID Connect 協定簡介
系列文
30 天與九頭蛇先生做好朋友23
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
孤獨一隻雞
iT邦研究生 5 級 ‧ 2022-10-07 10:42:17

寫得好詳細

我要留言

立即登入留言